#ifndef __ZHNOG_ES__
#define __ZHNOG_ES__
#include "Factory.hpp"
#include "user.hxx"
#include "message.hxx"
namespace bite_im
{
    class ESUser
    {
    public:
        using ptr = std::shared_ptr<ESUser>;
        ESUser(const ElasticPtr &es_client) : _es_client(es_client) {}
        bool createIndex()
        {
            bool ret = bite_im::ESIndex(_es_client, "user")
                           .append("user_id", "keyword", "standard", true)
                           .append("nickname")
                           .append("phone", "keyword", "standard", true)
                           .append("description", "text", "standard", false)
                           .append("avatar_id", "keyword", "standard", false)
                           .create();
            if (ret == false)
            {
                LOG_INFO("用户信息索引创建失败!");
                return false;
            }
            LOG_INFO("用户信息索引创建成功!");
            return true;
        }
        bool appendData(const std::string &user_id,
                        const std::string &phone,
                        const std::string &nickname,
                        const std::string &description,
                        const std::string &avatar_id)
        {
            // 数据的新增
            bool ret = bite_im::ESInsert(_es_client, "user")
                           .append("user_id", user_id)
                           .append("nickname", nickname)
                           .append("phone", phone)
                           .append("description", description)
                           .append("avatar_id", avatar_id)
                           .insert(user_id); // 如果user_id存在就是更新，不存在就是新增
            if (ret == false)
            {
                LOG_ERROR("用户信息新增失败!");
                return false;
            }
            LOG_INFO("用户信息新增成功!");
            return true;
        }

        std::vector<bite_im::User> search(const std::string &key, const std::vector<std::string> &user_id_list)
        {
            Json::Value json_users = bite_im::ESSearch(_es_client, "user")
                                         .append_should_match("phone.keyword", key)              // keyword整体直接进行查询，不需要分词
                                         .append_should_match("user_id.keyword", key)            // 电话和用户id都进行直接查询
                                         .append_should_match("nickname", key)                   // 昵称可进行分词查询
                                         .append_must_not_terms("user_id.keyword", user_id_list) // 不查询已知user_list
                                         .search();
            if (json_users.isArray() == false)
            {
                LOG_ERROR("用户数据检索结果不是数组类型");
                return std::vector<bite_im::User>();
            }
            int sz = json_users.size();
            LOG_INFO("用户数据检索成功，检索结果条目数量：{}", sz);

            std::vector<bite_im::User> ret;
            for (int i = 0; i < sz; i++)
            {
                User user;
                user.user_id(json_users[i]["_source"]["user_id"].asString());
                user.phone(json_users[i]["_source"]["phone"].asString());
                user.nickname(json_users[i]["_source"]["nickname"].asString());
                user.description(json_users[i]["_source"]["description"].asString());
                user.avatar_id(json_users[i]["_source"]["avatar_id"].asString());
                ret.push_back(user);
            }

            return ret;
        }

    private:
        ElasticPtr _es_client;
    };

    class ESMessage
    {
    public:
        using ptr = std::shared_ptr<ESMessage>;
        ESMessage(const ElasticPtr &es_client) : _es_client(es_client) {}
        bool createIndex()
        {
            bool ret = bite_im::ESIndex(_es_client, "message")
                           .append("user_id", "keyword", "standard", false)
                           .append("message_id", "keyword", "standard", false)
                           .append("create_time", "long", "standard", false)
                           .append("chat_session_id", "keyword", "standard", true)
                           .append("content")
                           .create();
            if (ret == false)
            {
                LOG_INFO("消息信息索引创建失败!");
                return false;
            }
            LOG_INFO("消息信息索引创建成功!");
            return true;
        }
        bool appendData(const std::string &user_id,
                        const std::string &message_id,
                        const long create_time,
                        const std::string &chat_session_id,
                        const std::string &content)
        {
            // 数据的新增
            bool ret = bite_im::ESInsert(_es_client, "message")
                           .append("user_id", user_id)
                           .append("message_id", message_id)
                           .append("create_time", create_time)
                           .append("chat_session_id", chat_session_id)
                           .append("content", content)
                           .insert(message_id); // 如果message_id存在就是更新，不存在就是新增
            if (ret == false)
            {
                LOG_ERROR("消息信息新增失败!");
                return false;
            }
            LOG_INFO("消息信息新增成功!");
            return true;
        }
        // 删除消息id对应的信息
        bool remove(const std::string &message_id)
        {
            bool ret = ESRemove(_es_client, "message").remove(message_id);
            if (ret == false)
            {
                LOG_ERROR("消息数据删除失败!");
                return false;
            }
            LOG_INFO("消息数据删除成功!");
            return true;
        }
        // 通过chat_session_id来获取若干条消息
        std::vector<bite_im::Message> search(const std::string &key, const std::string &chat_session_id)
        {
            Json::Value json_users = bite_im::ESSearch(_es_client, "message")
                                         .append_must_term("chat_session_id.keyword", chat_session_id)
                                         .append_must_match("content", key)
                                         .search();
            if (json_users.isArray() == false)
            {
                LOG_ERROR("消息数据检索结果不是数组类型");
                return std::vector<bite_im::Message>();
            }
            int sz = json_users.size();
            LOG_INFO("用户数据检索成功，检索结果条目数量：{}", sz);

            std::vector<bite_im::Message> ret;
            for (int i = 0; i < sz; i++)
            {
                bite_im::Message message;
                message.user_id(json_users[i]["_source"]["user_id"].asString());
                message.message_id(json_users[i]["_source"]["message_id"].asString());
                boost::posix_time::ptime ctime(boost::posix_time::from_time_t(
                    json_users[i]["_source"]["create_time"].asInt64()));
                message.create_time(ctime);
                message.session_id(json_users[i]["_source"]["chat_session_id"].asString());
                message.content(json_users[i]["_source"]["content"].asString());
                ret.push_back(message);
            }
            return ret;
        }
        // 获取满足key的所有消息，类似与微信主界面的搜索
        std::vector<bite_im::Message> searchAll(const std::string &key)
        {
            Json::Value json_users = bite_im::ESSearch(_es_client, "message")
                                         .append_must_match("content", key)
                                         .search();
            if (json_users.isArray() == false)
            {
                LOG_ERROR("消息数据检索结果不是数组类型");
                return std::vector<bite_im::Message>();
            }
            int sz = json_users.size();
            LOG_INFO("用户数据检索成功，检索结果条目数量：{}", sz);

            std::vector<bite_im::Message> ret;
            for (int i = 0; i < sz; i++)
            {
                bite_im::Message message;
                message.user_id(json_users[i]["_source"]["user_id"].asString());
                message.message_id(json_users[i]["_source"]["message_id"].asString());
                boost::posix_time::ptime ctime(boost::posix_time::from_time_t(
                    json_users[i]["_source"]["create_time"].asInt64()));
                message.create_time(ctime);
                message.session_id(json_users[i]["_source"]["chat_session_id"].asString());
                message.content(json_users[i]["_source"]["content"].asString());
                ret.push_back(message);
            }
            return ret;
        }

    private:
        ElasticPtr _es_client;
    };
}

#endif